// shared/so_wrapper.h
#pragma once
#include <dlfcn.h>
#include <stdexcept>
#include <string>

class SharedObject {
public:
    explicit SharedObject(const std::string& path, int flags = RTLD_NOW | RTLD_LOCAL)
    {
        handle_ = dlopen(path.c_str(), flags);
        if (!handle_)
            throw std::runtime_error(dlerror());
    }

    ~SharedObject()
    {
        if (handle_)
            dlclose(handle_);
    }

    // 获取符号并转换成目标类型
    template <typename T>
    T getSymbol(const std::string& name)
    {
        dlerror(); // 清空错误
        void* s = dlsym(handle_, name.c_str());
        const char* e = dlerror();
        if (e)
            throw std::runtime_error(e);
        return reinterpret_cast<T>(s);
    }

    // 禁止拷贝，允许移动
    SharedObject(const SharedObject&) = delete;
    SharedObject& operator=(const SharedObject&) = delete;
    SharedObject(SharedObject&& other) noexcept
        : handle_(other.handle_)
    {
        other.handle_ = nullptr;
    }

    SharedObject& operator=(SharedObject&& other) noexcept
    {
        if (this != &other) {
            if (handle_)
                dlclose(handle_);
            handle_ = other.handle_;
            other.handle_ = nullptr;
        }
        return *this;
    }

private:
    void* handle_ = nullptr;
};
